#!/usr/bin/env python
#-*- coding: utf-8 -*-

__license__ = """
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
DEALINGS IN THE SOFTWARE.
"""

import sys
import os
from tempfile import NamedTemporaryFile
import datetime
import kml
from PIL import Image
import ciafactbook
from string import Template
from optparse import OptionParser

T=Template
T.s = T.substitute

__version__ = "2010.09"


class progressBar:
    def __init__(self, minValue = 0, maxValue = 10, totalWidth=12):
        self.progBar = "[]"   # This holds the progress bar string
        self.min = minValue
        self.max = maxValue
        self.span = maxValue - minValue
        self.width = totalWidth
        self.amount = 0       # When amount == max, we are 100% done 
        self.updateAmount(0)  # Build progress bar string

    def updateAmount(self, newAmount = 0):
        if newAmount < self.min: newAmount = self.min
        if newAmount > self.max: newAmount = self.max
        self.amount = newAmount

        # Figure out the new percent done, round to an integer
        diffFromMin = float(self.amount - self.min)
        percentDone = (diffFromMin / float(self.span)) * 100.0
        percentDone = round(percentDone)
        percentDone = int(percentDone)

        # Figure out how many hash bars the percentage should be
        allFull = self.width - 2
        numHashes = (percentDone / 100.0) * allFull
        numHashes = int(round(numHashes))

        # build a progress bar with hashes and spaces
        self.progBar = "[" + '#'*numHashes + ' '*(allFull-numHashes) + "]"

        # figure out where to put the percentage, roughly centered
        percentPlace = (len(self.progBar) / 2) - len(str(percentDone)) 
        percentString = str(percentDone) + "%"

        # slice the percentage into the bar
        self.progBar = self.progBar[0:percentPlace] + percentString + \
            self.progBar[percentPlace+len(percentString):]

    def __str__(self):
        return str(self.progBar)

def printLicense():
    print __license__
    sys.exit(0)
        
def showVersion(exeunt=False):
    msg=T("wfb2kml Version $version").substitute(version=__version__)      
    print msg
    print "Copyright © 2010 Rob A. Shinn."
    print "Open Source Software. See wfb2kml -L for license info."
    if exeunt: 
        sys.exit(0)
  
optParser = OptionParser(usage = "usage: %prog [options] <filename>")
#optParser.add_option("-h", "--help", action="help")
optParser.add_option("-b", "--balloon-bg", dest="balloonBg",
                     help="set background color to abgr", metavar="abgr",
                     default="FFA6C6B9")
optParser.add_option("-f", "--balloon-fg", dest="balloonFg",
                      help="set foreground color to abgr", metavar="abgr",
                      default="FF000000")
optParser.add_option('-H', "--flag-height", dest="flagHeight",
                     help="set maximum flag height", metavar="height", 
                     default=54.0)
optParser.add_option("-n",  "--number", dest="num",
                     help="set number of countries to num for testing",
                     metavar="num", default=0)
optParser.add_option("-r", "--view-range", dest="range",
                     help="set the range (in meters) for each view", 
                     metavar="range", default=2000000)
optParser.add_option("-w", "--initial-view-range", dest="gRange",
                     help="set initial (global) view range", metavar="range",
                     default=10000000)
optParser.add_option("-V", "--show-version", dest="exeunt", action="store_true",
                     default=False, help="show version info and exit.")
optParser.add_option("-L", "--show-license", dest="showlic",
                     action="store_true", default=False,
                      help="show license info and exit")

  
options, args = optParser.parse_args()
if len(args) != 1 and not (options.showlic or options.exeunt):
    optParser.print_help()
    sys.exit(0)
else:
    kmzFilename = args[0]

showVersion(options.exeunt)

if options.showlic:
    printLicense()

projectUrl = "http://code.google.com/p/wfb2kml"
comment = T("Document generated $stamp by wfb2kml. See $url")
docName = "CIA World Factbook"
timestamp = datetime.datetime.now().isoformat()
print "Fetching country/region codes ...",
codes = ciafactbook.names.keys()
codes.sort()
msg = T('$num countries/regions found')
print msg.substitute(num=len(codes))
mode = kml.altitudeMode()
view = kml.LookAt()
view.latitude = 0
view.longitude = 0
view.range = float(options.gRange)
document = kml.Document()
document.name = docName
desc = T('Data from the <a href="$url">$what</a> site. Generated by wfb2kml '+
        '$version at $when. See $projurl for more details.'+
         '<br/>All data courtesy of the U.S. Central Intelligence Agency.')
document.description = desc.substitute(url=ciafactbook.names.url,
                                       projurl=projectUrl,
                                       what=docName, 
                                       when=timestamp, 
                                       version=__version__)
document.View = view
document.visibility = True
document.open = False
balloonStyle = kml.BalloonStyle()
balloonStyle.text = '$[description]<br/><br/>Other sources: <a href='+\
    '"http://en.wikipedia.org/wiki/$[name]">Wikipedia</a>, <a href="http://'+\
    'www.google.com/search?q=$[name]">Google</a>'
balloonStyle.bgColor = int('0x'+ options.balloonBg, 16)
balloonStyle.textColor = int('0x'+options.balloonFg, 16)
iconStyle = kml.IconStyle()
iconStyle.scale=0.75
style = kml.Style('country')
style.BalloonStyle = balloonStyle
style.IconStyle = iconStyle
document.addStyle(style)
icon=kml.Icon(href='root://icons/palette-3.png')
icon.x = 96
icon.y = 128
icon.width = 32
icon.height = 32
iconStyle = kml.IconStyle()
iconStyle.Icon = icon

balloonStyle = kml.BalloonStyle()
balloonStyle.text = '$[description]<br/><br/>Other sources: <a href='+\
    '"http://en.wikipedia.org/wiki/$[name]">Wikipedia</a>, <a href="http://'+\
    'www.google.com/search?q=$[name]">Google</a>'
balloonStyle.bgColor = int('0x'+ options.balloonBg, 16)
balloonStyle.textColor = int('0x'+options.balloonFg, 16)
style = kml.Style('noflag')
style.BalloonStyle = balloonStyle
style.IconStyle = iconStyle
document.addStyle(style)
print "Fetching country data: "
n=0
# uncomment the following line for testing!
if options.num:
    codes=codes[0:int(options.num)]
prog = progressBar(0, len(codes), 77)
countries = []
for code in codes:
    n+=1
    country = ciafactbook.Country(code)
    # force data cacheing:
    dummy=country.latitude
    prog.updateAmount(n)
    print "\r", prog,
    sys.stdout.flush()
    countries.append(country)
print 
print "Generating DOM data: "
n=0
prog = progressBar(0, len(countries), 77)
for country in countries:
    n+=1
    code = country.code
    prog.updateAmount(n)
    print "\r", prog,
    sys.stdout.flush()
    point = kml.Point()
    point.latitude = country.latitude
    point.longitude = country.longitude
    point.altitudeMode = mode.clampToGround
    view = kml.LookAt()
    view.latitude = country.latitude
    view.longitude = country.longitude
    view.range = float(options.range)
    style = kml.Style(id=code)
    d = dict(url = country.url, name = country.name,
             src = T("images/$code.png").substitute(code=country.code),
             desc = country.description, code = country.code,
             year = datetime.date.today().year)
    if country.flag:
        icon = kml.Icon(href=d["src"])
        iconStyle = kml.IconStyle()
        iconStyle.Icon=icon
        style.IconStyle=iconStyle
    snippet = T(r'<a href="$url">$name entry at the CIA World Factbook</a>').substitute(d)
    snippet = kml.Snippet(snippet)
    
    if country.flag:
        desc = '<div><a href="$url"><h3>$name<h3></a></div><a href="$url">'+\
            '<img src="$src" alt="Flag of $code" title="$name" '+\
            'style="margin: 10 px; float: left;"/></a><br/><br/>$desc'+\
            '<br/><a href="$url">Public domain material courtesy of CIA, $year</a>.<br/>'+\
            '<a href="$url">More information...</a>  '''
    else:
        desc = '<div><h3><a href="$url">$name</a></h3></div><br/><br/>$desc'+\
            '<br/><a href="$url">Public domain material courtesy of CIA, $year</a>.<br/>'+\
            '<a href="$url">More information...</a>'
    desc=T(desc).substitute(d)
    place = kml.Placemark()
    place.name=country.name
    place.description = desc
    place.Vector = point
    place.View = view
    if country.flag:
        place.styleUrl = "#country"
    else:
        place.styleUrl = "#noflag"
    place.addStyle(style)
    place.Snippet = snippet
    document.addChildFeature(place)
print
filename = "doc.kml"
if os.path.exists(filename):
    os.remove(filename)

msg=T("Generating KML file '$file' ...")
print msg.substitute(file=filename), 
sys.stdout.flush()
kmlDocument = kml.kml(filename)
kmlDocument.addComment(comment.substitute(stamp=timestamp, url=projectUrl))
kmlDocument.addChildFeature(document)
kmlDocument.write()
kmlDocument.close()
print "done!"
n = 0 
print "Fetching flags:"
if not os.path.exists('images'):
    os.mkdir('images')
prog = progressBar(0, len(countries), 77)
for country in countries:
    n+=1
    prog.updateAmount(n)
    print "\r", prog,
    sys.stdout.flush()
    url = country.flag
    if url:
        img = ciafactbook.wget(url)
        tmpfile = NamedTemporaryFile(delete=False)
        tmpfilename = tmpfile.name
        tmpfile.write(img)
        tmpfile.flush()
        tmpfile.close()
        image = Image.open(tmpfilename)
        width, height = image.size
        maxHeight = options.flagHeight
        factor = maxHeight/float(height)
        newWidth = int(width * factor)
        newHeight = int(maxHeight)
        image = image.resize((newWidth, newHeight), Image.ANTIALIAS)
        outfile = T("images/$code.png")
        image.save(outfile.substitute(code=country.code), "PNG")
        os.remove(tmpfilename)
print
print T("Writing KMZ $file ... ").substitute(file=kmzFilename)

kmz = kml.kmz(kml.kml(filename), kmzFilename, 'w')
kmz.write()
kmz.close()

    
    
    
    

     
    
    
